home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / dflat_r_.arc / DIALBOX.C < prev    next >
Text File  |  1991-10-02  |  23KB  |  977 lines

  1. /* ----------------- dialbox.c -------------- */
  2.  
  3. #include <string.h>
  4. #include <ctype.h>
  5. #include <stdlib.h>
  6. #if MSC | WATCOM
  7. #include <direct.h>
  8. #else
  9. #include <dir.h>
  10. #endif
  11. #include <dos.h>
  12. #include <io.h>
  13. #include "dflat.h"
  14.  
  15. static char path[MAXPATH];
  16. static char drive[MAXDRIVE] = " :";
  17. static char dir[MAXDIR];
  18. static char name[MAXFILE];
  19. static char ext[MAXEXT];
  20.  
  21. #ifdef INCLUDE_DIALOG_BOXES
  22.  
  23. static int inFocusCommand(DBOX *);
  24. static void SetRadioButton(WINDOW, DBOX *, CTLWINDOW *);
  25. static void InvertCheckBox(WINDOW, CTLWINDOW *);
  26. static void dbShortcutKeys(WINDOW, DBOX *, int);
  27. static int ControlProc(WINDOW, MESSAGE, PARAM, PARAM);
  28. static void ChangeFocus(WINDOW, int);
  29. static CTLWINDOW *AssociatedControl(DBOX *, enum commands);
  30. static void PressButtons(WINDOW);
  31.  
  32. #ifdef INCLUDE_SYSTEM_MENUS
  33. static int SysMenuOpen;
  34. #endif
  35.  
  36. int DialogProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  37. {
  38.     DBOX *db;
  39.     CTLWINDOW *ct;
  40.  
  41.     db = wnd->extension;
  42.  
  43.     switch (msg)    {
  44.         case SETFOCUS:
  45.             if (wnd->Modal)    {
  46.                 if (p1)
  47.                     SendMessage(inFocus, SETFOCUS, FALSE, 0);
  48.                 inFocus = p1 ? wnd : NULLWND;
  49.                 return TRUE;
  50.             }
  51.             break;
  52.         case SHIFT_CHANGED:
  53.             if (wnd->Modal)
  54.                 return TRUE;
  55.             break;
  56.         case LEFT_BUTTON:
  57. #ifdef INCLUDE_SYSTEM_MENUS
  58.             if (WindowSizing || WindowMoving)
  59.                 return FALSE;
  60. #endif
  61.             if (HitControlBox(wnd, p1-GetLeft(wnd), p2-GetTop(wnd)))    {
  62.                 PostMessage(wnd, KEYBOARD, ' ', ALTKEY);
  63.                 return TRUE;
  64.             }
  65.             ct = db->ctl;
  66.             while (ct->class)    {
  67.                 int mx = (int) p1 - GetClientLeft(wnd);
  68.                 int my = (int) p2 - GetClientTop(wnd);
  69.                 if (ct->class == RADIOBUTTON)    {
  70.                     if (my == ct->dwnd.y && mx == ct->dwnd.x+1)
  71.                         SetRadioButton(wnd, db, ct);
  72.                 }
  73.                 else if (ct->class == CHECKBOX)    {
  74.                     if (my == ct->dwnd.y && mx == ct->dwnd.x+1)
  75.                         InvertCheckBox(wnd, ct);
  76.                 }
  77.                 ct++;
  78.             }
  79.             break;
  80.         case PAINT:
  81.             if (!isVisible(wnd))
  82.                 break;
  83.             if (!p2)
  84.                 BaseWndProc(DIALOG, wnd, msg, p1, p2);
  85.             ct = p2 ? (CTLWINDOW *) p2 : db->ctl;
  86.             while (ct->class)    {
  87.                 if (ct == wnd->dFocus &&
  88.                         (ct->class == RADIOBUTTON ||
  89.                             ct->class == CHECKBOX))
  90.                     SetReverseColor(wnd);
  91.                 else 
  92.                     SetStandardColor(wnd);
  93.                 if (ct->class == RADIOBUTTON)    {
  94.                     char rb[] = "( )";
  95.                     if (ct->setting)
  96.                         rb[1] = 7;
  97.                     writeline(wnd, rb, ct->dwnd.x+1, ct->dwnd.y+1, FALSE);
  98.                 }
  99.                 else if (ct->class == CHECKBOX)    {
  100.                     char rb[] = "[ ]";
  101.                     if (ct->setting)
  102.                         rb[1] = 'X';
  103.                     writeline(wnd, rb, ct->dwnd.x+1, ct->dwnd.y+1, FALSE);
  104.                 }
  105.                 else if (ct->class == TEXT && ct->vtext != NULL)    {
  106.                     char *cp = ct->vtext;
  107.                     int len = min(ct->dwnd.h, MsgHeight(cp));
  108.                     int i;
  109.                     for (i = 0; i < len; i++)    {
  110.                         int mlen;
  111.                         char *txt = cp;
  112.                         char *cp1 = cp;
  113.                         char *np = strchr(cp, '\n');
  114.                         if (np != NULL)
  115.                             *np = '\0';
  116.                         mlen = strlen(cp);
  117.                         while ((cp1 = strchr(cp1, SHORTCUTCHAR)) != NULL)    {
  118.                             mlen += 3;
  119.                             cp1++;
  120.                         }
  121.                         if (np != NULL)
  122.                             *np = '\n';
  123.                         if ((txt = malloc(mlen+1)) != NULL)    {
  124.                              CopyCommand(txt, cp, FALSE, WndBackground(wnd));
  125.                             txt[mlen] = '\0';
  126.                             writeline(wnd, txt, ct->dwnd.x+1, ct->dwnd.y+i+1, TRUE);
  127.                             if ((cp = strchr(cp, '\n')) != NULL)
  128.                                 cp++;
  129.                             free(txt);
  130.                         }
  131.                     }
  132.                 }
  133.                 else if (ct->class != BOX)    {
  134.                     if (ct->itext != NULL)    {
  135.                         WINDOW cwnd = ct->wnd;
  136.                         static unsigned char txt[200];
  137.                         memset(txt, '\0', sizeof txt);
  138.                         if (ct->class == BUTTON && ct->setting == OFF)    {
  139.                             txt[0] = CHANGECOLOR;
  140.                             txt[1] = cwnd->WindowColors [HILITE_COLOR] [FG] | 0x80;
  141.                             txt[2] = cwnd->WindowColors [STD_COLOR] [BG] | 0x80;
  142.                         }
  143.                         CopyCommand(txt+strlen(txt), ct->itext, !ct->setting,
  144.                             WndBackground(cwnd));
  145.                         SendMessage(cwnd, CLEARTEXT, 0, 0);
  146.                         SendMessage(cwnd, ADDTEXT, (PARAM) txt, 0);
  147.                     }
  148.                 }
  149.                 ct++;
  150.                 if (p2)
  151.                     break;
  152.             }
  153.             return TRUE;
  154.         case KEYBOARD:
  155.             switch ((int)p1)    {
  156.                 case F1:
  157.                     ct = wnd->dFocus;
  158.                     if (ct != NULL)
  159.                         if (DisplayHelp(wnd, ct->help))
  160.                             return TRUE;
  161.                     break;
  162.                 case '\t':
  163.                     ChangeFocus(wnd, TRUE);
  164.                     break;
  165.                 case CTRL_FIVE:        /* same as SHIFT-TAB */
  166.                     if ((int)p2 & (LEFTSHIFT | RIGHTSHIFT))
  167.                         ChangeFocus(wnd, FALSE);
  168.                     break;
  169.                 case BS:
  170.                 case UP:
  171. #ifdef INCLUDE_SYSTEM_MENUS
  172.                     if (WindowMoving || WindowSizing)
  173.                         return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  174. #endif
  175.                     ChangeFocus(wnd, FALSE);
  176.                     break;
  177.                 case FWD:
  178.                 case DN:
  179. #ifdef INCLUDE_SYSTEM_MENUS
  180.                     if (WindowMoving || WindowSizing)
  181.                         return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  182. #endif
  183.                     ChangeFocus(wnd, TRUE);
  184.                     break;
  185. #ifdef INCLUDE_SYSTEM_MENUS
  186.                 case ' ':
  187.                     if (((int)p2 & ALTKEY) && TestAttribute(wnd, CONTROLBOX))    {
  188.                         SysMenuOpen = TRUE;
  189.                         BuildSystemMenu(wnd);
  190.                     }
  191.                     break;
  192. #endif
  193.                 case CTRL_F4:
  194.                 case ESC:
  195. #ifdef INCLUDE_SYSTEM_MENUS
  196.                     if (!(WindowMoving || WindowSizing))
  197. #endif
  198.                         SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  199.                 default:
  200.                     /* ------ search all the shortcut keys ----- */
  201.                     dbShortcutKeys(wnd, db, (int) p1);
  202.                     break;
  203.             }
  204.             if ((int)p1 == ' ' || (int)p1 == '\r')
  205.                 PressButtons(wnd);
  206.             if (wnd->Modal)
  207.                 return TRUE;
  208.             break;
  209. #ifdef INCLUDE_SYSTEM_MENUS
  210.         case CLOSE_POPDOWN:
  211.             SysMenuOpen = FALSE;
  212.             break;
  213. #endif
  214.         case LB_SELECTION:
  215.         case LB_CHOOSE:
  216. #ifdef INCLUDE_SYSTEM_MENUS
  217.             if (SysMenuOpen)
  218.                 return TRUE;
  219. #endif
  220.             SendMessage(wnd, COMMAND, inFocusCommand(db), msg);
  221.             break;
  222.         case COMMAND:
  223.             switch ((int) p1)    {
  224.                 case ID_OK:
  225.                 case ID_CANCEL:
  226.                     wnd->ReturnCode = (int) p1;
  227.                     if (wnd->Modal)
  228.                         PostMessage(wnd, ENDDIALOG, 0, 0);
  229.                     else
  230.                         SendMessage(wnd, CLOSE_WINDOW, TRUE, 0);
  231.                     return TRUE;
  232. #ifdef INCLUDE_HELP
  233.                 case ID_HELP:
  234.                     return DisplayHelp(wnd, db->HelpName);
  235. #endif
  236.                 default:
  237.                     break;
  238.             }
  239.             break;
  240.         case CLOSE_WINDOW:
  241.             if (!p1)    {
  242.                 SendMessage(wnd, COMMAND, ID_CANCEL, 0);
  243.                 return TRUE;
  244.             }
  245.             break;
  246.         default:
  247.             break;
  248.     }
  249.     return BaseWndProc(DIALOG, wnd, msg, p1, p2);
  250. }
  251.  
  252. int DialogBox(WINDOW wnd, DBOX *db, int Modal,
  253.     int (*wndproc)(struct window *, enum messages, PARAM, PARAM))
  254. {
  255.     int rtn;
  256.     WINDOW Dwnd;
  257.     CTLWINDOW *ct;
  258.     WINDOW oldFocus = inFocus;
  259.     Dwnd = CreateWindow(DIALOG,
  260.                         db->dwnd.title,
  261.                         db->dwnd.x,
  262.                         db->dwnd.y,
  263.                         db->dwnd.h,
  264.                         db->dwnd.w,
  265.                         db,
  266.                         wnd,
  267.                         wndproc,
  268.                         Modal ? SAVESELF : 0);
  269.     Dwnd->Modal = Modal;
  270.     ct = db->ctl;
  271.     while (ct->class)    {
  272.         if (ct->class != TEXT &&
  273.                 ct->class != RADIOBUTTON &&
  274.                     ct->class != CHECKBOX)    {
  275.             WINDOW cwnd;
  276.             int attrib = VISIBLE;
  277.             if (TestAttribute(Dwnd, NOCLIP))
  278.                 attrib |= NOCLIP;
  279.             ct->vtext = ct->itext;
  280.             ct->setting = ct->isetting;
  281.             if (ct->class == EDITBOX && ct->dwnd.h > 1)
  282.                 attrib |= (MULTILINE | HASBORDER);
  283.             else if (ct->class == LISTBOX || ct->class == TEXTBOX)
  284.                 attrib |= HASBORDER;
  285.             cwnd = CreateWindow(ct->class,
  286.                                 ct->dwnd.title,
  287.                                 ct->dwnd.x+GetClientLeft(Dwnd),
  288.                                 ct->dwnd.y+GetClientTop(Dwnd),
  289.                                 ct->dwnd.h,
  290.                                 ct->dwnd.w,
  291.                                 NULL,
  292.                                 Dwnd,
  293.                                 ControlProc,
  294.                                 attrib);
  295.             ct->wnd = cwnd;
  296.             if (ct->class != BOX && Dwnd->dFocus == NULL)
  297.                 Dwnd->dFocus = ct;
  298.         }
  299.         else if (ct->class == TEXT && ct->itext != NULL)    {
  300.             int len = strlen(ct->itext)+1;
  301.             if ((ct->vtext = calloc(1, len)) != NULL)
  302.                 strncpy(ct->vtext, ct->itext, len);
  303.         }
  304.         else if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  305.             ct->setting = ct->isetting;
  306.         ct++;
  307.     }
  308.     SendMessage(((CTLWINDOW *)(Dwnd->dFocus))->wnd, SETFOCUS, TRUE, 0);
  309.     SendMessage(Dwnd, SHOW_WINDOW, 0, 0);
  310.     SendMessage(Dwnd, INITIATE_DIALOG, 0, 0);
  311.     if (Modal)    {
  312.         SendMessage(Dwnd, CAPTURE_MOUSE, 0, 0);
  313.         SendMessage(Dwnd, CAPTURE_KEYBOARD, 0, 0);
  314.         while (dispatch_message())
  315.             ;
  316.         rtn = Dwnd->ReturnCode == ID_OK;
  317.         SendMessage(Dwnd, RELEASE_MOUSE, 0, 0);
  318.         SendMessage(Dwnd, RELEASE_KEYBOARD, 0, 0);
  319.         SendMessage(Dwnd, CLOSE_WINDOW, TRUE, 0);
  320.         SendMessage(oldFocus, SETFOCUS, TRUE, TRUE);
  321.         if (rtn)    {
  322.             ct = db->ctl;
  323.             while (ct->class)    {
  324.                 if (ct->class == RADIOBUTTON || ct->class == CHECKBOX)
  325.                     ct->isetting = ct->setting;
  326.                 ct++;
  327.             }
  328.         }
  329.         return rtn;
  330.     }
  331.     return FALSE;
  332. }
  333.  
  334. static int inFocusCommand(DBOX *db)
  335. {
  336.     CTLWINDOW *ct = db->ctl;
  337.     while (ct->class)    {
  338.         if (ct->wnd == inFocus)
  339.             return ct->command;
  340.         ct++;
  341.     }
  342.     return -1;
  343. }
  344.  
  345. CTLWINDOW *FindCommand(DBOX *db, enum commands cmd, int class)
  346. {
  347.     CTLWINDOW *ct = db->ctl;
  348.     while (ct->class)    {
  349.         if (ct->class == class)
  350.             if (cmd == ct->command)
  351.                 return ct;
  352.         ct++;
  353.     }
  354.     return NULL;
  355. }
  356.  
  357. WINDOW ControlWindow(DBOX *db, enum commands cmd)
  358. {
  359.     CTLWINDOW *ct = db->ctl;
  360.     while (ct->class)    {
  361.         if (ct->class != TEXT && cmd == ct->command)
  362.             return ct->wnd;
  363.         ct++;
  364.     }
  365.     return NULLWND;
  366. }
  367.  
  368. CTLWINDOW *ControlBox(DBOX *db, WINDOW wnd)
  369. {
  370.     CTLWINDOW *ct = db->ctl;
  371.     while (ct->class)    {
  372.         if (ct->class != TEXT && wnd == ct->wnd)
  373.             return ct;
  374.         ct++;
  375.     }
  376.     return NULL;
  377. }
  378.  
  379. void PushRadioButton(DBOX *db, enum commands cmd)
  380. {
  381.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  382.     if (ct != NULL)    {
  383.         SetRadioButton(NULLWND, db, ct);
  384.         ct->isetting = ON;
  385.     }
  386. }
  387.  
  388. static struct {
  389.     CTLWINDOW *rct;
  390. } rbs[MAXRADIOS];
  391.  
  392. static void SetRadioButton(WINDOW wnd, DBOX *db, CTLWINDOW *ct)
  393. {
  394.     CTLWINDOW *ctt = db->ctl;
  395.     int i;
  396.  
  397.     /* --- clear all the radio buttons
  398.                 in this group on the dialog box --- */
  399.  
  400.     /* -------- build a table of all radio buttons at the
  401.             same x vector ---------- */
  402.     for (i = 0; i < MAXRADIOS; i++)
  403.         rbs[i].rct = NULL;
  404.     while (ctt->class)    {
  405.         if (ctt->class == RADIOBUTTON)
  406.             if (ct->dwnd.x == ctt->dwnd.x)
  407.                 rbs[ctt->dwnd.y].rct = ctt;
  408.         ctt++;
  409.     }
  410.  
  411.     /* ----- find the start of the radiobutton group ---- */
  412.     i = ct->dwnd.y;
  413.     while (i >= 0 && rbs[i].rct != NULL)
  414.         --i;
  415.     /* ---- ignore everthing before the group ------ */
  416.     while (i >= 0)
  417.         rbs[i--].rct = NULL;
  418.  
  419.     /* ----- find the end of the radiobutton group ---- */
  420.     i = ct->dwnd.y;
  421.     while (i < MAXRADIOS && rbs[i].rct != NULL)
  422.         i++;
  423.     /* ---- ignore everthing past the group ------ */
  424.     while (i < MAXRADIOS)
  425.         rbs[i++].rct = NULL;
  426.  
  427.     for (i = 0; i < MAXRADIOS; i++)    {
  428.         if (rbs[i].rct != NULL)    {
  429.             rbs[i].rct->setting = OFF;
  430.             if (wnd != NULLWND)
  431.                 SendMessage(wnd, PAINT, 0, (PARAM) rbs[i].rct);
  432.         }
  433.     }
  434.     ct->setting = ON;
  435.     if (wnd != NULLWND)
  436.         SendMessage(wnd, PAINT, 0, (PARAM) ct);
  437. }
  438.  
  439. int RadioButtonSetting(DBOX *db, enum commands cmd)
  440. {
  441.     CTLWINDOW *ct = FindCommand(db, cmd, RADIOBUTTON);
  442.     if (ct != NULL)
  443.         return (ct->setting == ON);
  444.     return FALSE;
  445. }
  446.  
  447. static void ControlSetting(DBOX *db, enum commands cmd,
  448.                                     int class, int setting)
  449. {
  450.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  451.     if (ct != NULL)
  452.         ct->isetting = setting;
  453. }
  454.  
  455. void SetCheckBox(DBOX *db, enum commands cmd)
  456. {
  457.     ControlSetting(db, cmd, CHECKBOX, ON);
  458. }
  459.  
  460. void ClearCheckBox(DBOX *db, enum commands cmd)
  461. {
  462.     ControlSetting(db, cmd, CHECKBOX, OFF);
  463. }
  464.  
  465. void EnableButton(DBOX *db, enum commands cmd)
  466. {
  467.     ControlSetting(db, cmd, BUTTON, ON);
  468. }
  469.  
  470. void DisableButton(DBOX *db, enum commands cmd)
  471. {
  472.     ControlSetting(db, cmd, BUTTON, OFF);
  473. }
  474.  
  475. int CheckBoxSetting(DBOX *db, enum commands cmd)
  476. {
  477.     CTLWINDOW *ct = FindCommand(db, cmd, CHECKBOX);
  478.     if (ct != NULL)
  479.         return (ct->isetting == ON);
  480.     return FALSE;
  481. }
  482.  
  483. static void InvertCheckBox(WINDOW wnd, CTLWINDOW *ct)
  484. {
  485.     ct->setting ^= ON;
  486.     SendMessage(wnd, PAINT, 0, (PARAM) ct);
  487. }
  488.  
  489. char *GetDlgTextString(DBOX *db, enum commands cmd, CLASS class)
  490. {
  491.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  492.     if (ct != NULL)
  493.         return ct->itext;
  494.     else
  495.         return NULL;
  496. }
  497.  
  498. void SetDlgTextString(DBOX *db, enum commands cmd, char *text, CLASS class)
  499. {
  500.     CTLWINDOW *ct = FindCommand(db, cmd, class);
  501.     if (ct != NULL)    {
  502.         ct->itext = realloc(ct->itext, strlen(text)+1);
  503.         if (ct->itext != NULL)
  504.             strcpy(ct->itext, text);
  505.     }
  506. }
  507.  
  508. void PutItemText(WINDOW wnd, enum commands cmd, char *text)
  509. {
  510.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  511.  
  512.     if (ct == NULL)
  513.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  514.     if (ct == NULL)
  515.         ct = FindCommand(wnd->extension, cmd, TEXT);
  516.     if (ct != NULL)        {
  517.         WINDOW cwnd = (WINDOW) (ct->wnd);
  518.         MESSAGE msg = ADDTEXT;
  519.         switch (ct->class)    {
  520.             case EDITBOX:
  521.                 msg = EB_PUTTEXT;
  522.             case TEXTBOX:
  523.                 SendMessage(cwnd, msg, (PARAM) text, 0);
  524.                 if (ct->class == EDITBOX && !isMultiLine(cwnd))
  525.                     SendMessage(cwnd, PAINT, 0, 0);
  526.                 if (cwnd->wlines > ClientHeight(cwnd) &&
  527.                         !TestAttribute(cwnd, VSCROLLBAR))    {
  528.                     AddAttribute(cwnd, VSCROLLBAR);
  529.                     SendMessage(cwnd, BORDER, 0, 0);
  530.                 }
  531.                 break;
  532.             case TEXT:    {
  533.                 ct->vtext = realloc(ct->vtext, strlen(text)+1);
  534.                 if (ct->vtext != NULL)
  535.                     strcpy(ct->vtext, text);
  536.                 SendMessage(wnd, PAINT, 0, (PARAM) ct);
  537.                 break;
  538.             }
  539.             default:
  540.                 break;
  541.         }
  542.     }
  543. }
  544.  
  545. void GetItemText(WINDOW wnd, enum commands cmd, char *text, int len)
  546. {
  547.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, EDITBOX);
  548.  
  549.     if (ct == NULL)
  550.         ct = FindCommand(wnd->extension, cmd, TEXTBOX);
  551.     if (ct == NULL)
  552.         ct = FindCommand(wnd->extension, cmd, TEXT);
  553.     if (ct != NULL)    {
  554.         WINDOW cwnd = (WINDOW) (ct->wnd);
  555.         switch (ct->class)    {
  556.             case TEXTBOX:
  557.                 if (cwnd != NULL)    {
  558.                     char *cp = GetText(cwnd);
  559.                     if (cp != NULL)
  560.                         strncpy(text, cp, len);
  561.                 }
  562.                 break;
  563.             case EDITBOX:
  564.                 if (cwnd != NULL)
  565.                     SendMessage(cwnd, EB_GETTEXT, (PARAM) text, len);
  566.                 break;
  567.             case TEXT:
  568.                 strncpy(text, ct->vtext, len);
  569.                 break;
  570.             default:
  571.                 break;
  572.         }
  573.     }
  574. }
  575.  
  576. void GetDlgListText(WINDOW wnd, char *text, enum commands cmd)
  577. {
  578.     CTLWINDOW *ct = FindCommand(wnd->extension, cmd, LISTBOX);
  579.     int sel = SendMessage(ct->wnd, LB_CURRENTSELECTION, 0, 0);
  580.     SendMessage(ct->wnd, LB_GETTEXT, (PARAM) text, sel);
  581. }
  582.  
  583. static int dircmp(const void *c1, const void *c2)
  584. {
  585.     return stricmp(*(char **)c1, *(char **)c2);
  586. }
  587.  
  588. int DlgDirList(WINDOW wnd, char *fspec,
  589.                 enum commands nameid, enum commands pathid,
  590.                 unsigned attrib)
  591. {
  592.     int ax, i = 0, criterr = 1;
  593.     struct ffblk ff;
  594.     CTLWINDOW *ct = FindCommand(wnd->extension, nameid, LISTBOX);
  595.     WINDOW lwnd;
  596.     char **dirlist = NULL;
  597.  
  598.     CreatePath(path, fspec, TRUE, TRUE);
  599.  
  600.     if (ct != NULL)    {
  601.         lwnd = ct->wnd;
  602.         SendMessage(ct->wnd, CLEARTEXT, 0, 0);
  603.  
  604.         if (attrib & 0x8000)    {
  605.             union REGS regs;
  606.             char drname[15];
  607.             unsigned int cd, dr;
  608.  
  609. #if MSC | WATCOM
  610.             _dos_getdrive(&cd);
  611.             cd -= 1;
  612. #else
  613.             cd = getdisk();
  614. #endif
  615.             for (dr = 0; dr < 26; dr++)    {
  616.                 unsigned ndr;
  617.                 setdisk(dr);
  618. #if MSC | WATCOM
  619.                 _dos_getdrive(&ndr);
  620.                 ndr -= 1;
  621. #else
  622.                 ndr = getdisk();
  623. #endif
  624.                 if (ndr == dr)    {
  625.                     /* ------- test for remapped B drive ------- */
  626.                     if (dr == 1)    {
  627.                         regs.x.ax = 0x440e;        /* IOCTL function 14 */
  628.                         regs.h.bl = dr+1;
  629.                         int86(DOS, ®s, ®s);
  630.                         if (regs.h.al != 0)
  631.                             continue;
  632.                     }
  633.  
  634.                     sprintf(drname, "[%c:]", dr+'A');
  635.  
  636.                     /* ------ test for network or RAM disk ---- */
  637.                     regs.x.ax = 0x4409;        /* IOCTL function 9 */
  638.                     regs.h.bl = dr+1;
  639.                     int86(DOS, ®s, ®s);
  640.                     if (!regs.x.cflag)    {
  641.                         if (regs.x.dx & 0x1000)
  642.                             strcat(drname, " (Network)");
  643.                         else if (regs.x.dx == 0x0800)
  644.                             strcat(drname, " (RAMdisk)");
  645.                     }
  646.                     SendMessage(lwnd, ADDTEXT, (PARAM) drname, 0);
  647.                 }
  648.             }
  649.             setdisk(cd);
  650.         }
  651.  
  652.         while (criterr == 1)    {
  653.             ax = findfirst(path, &ff, attrib & 0x3f);
  654.             criterr = TestCriticalError();
  655.         }
  656.         if (criterr)
  657.             return FALSE;
  658.         while (ax == 0)    {
  659.             if (!((attrib & 0x4000) &&
  660.                     (ff.ff_attrib & (attrib & 0x3f)) == 0) &&
  661.                         strcmp(ff.ff_name, "."))    {
  662.                 char fname[15];
  663.                 sprintf(fname, (ff.ff_attrib & 0x10) ?
  664.                                 "[%s]" : "%s" , ff.ff_name);
  665.                 dirlist = realloc(dirlist, sizeof(char *)*(i+1));
  666.                 if (dirlist != NULL)    {
  667.                     dirlist[i] = malloc(strlen(fname)+1);
  668.                     if (dirlist[i] != NULL)
  669.                         strcpy(dirlist[i], fname);
  670.                     i++;
  671.                 }
  672.             }
  673.             ax = findnext(&ff);
  674.         }
  675.         if (dirlist != NULL)    {
  676.             int j;
  677.             /* -- sort file/drive/directory list box data -- */
  678.             qsort(dirlist, i, sizeof(void *), dircmp);
  679.  
  680.             /* ---- send sorted list to list box ---- */
  681.             for (j = 0; j < i; j++)    {
  682.                 SendMessage(lwnd, ADDTEXT, (PARAM) dirlist[j], 0);
  683.                 free(dirlist[j]);
  684.             }
  685.             free(dirlist);
  686.         }
  687. #ifdef INCLUDE_SCROLLBARS
  688.         if (lwnd->wlines > ClientHeight(lwnd))
  689.             AddAttribute(lwnd, VSCROLLBAR);
  690.         else
  691.             ClearAttribute(lwnd, VSCROLLBAR);
  692. #endif
  693.         SendMessage(lwnd, SHOW_WINDOW, 0, 0);
  694.     }
  695.  
  696.     if (pathid)    {
  697.         fnmerge(path, drive, dir, NULL, NULL);
  698.         PutItemText(wnd, pathid, path);
  699.     }
  700.  
  701.     return TRUE;
  702. }
  703.  
  704. static CTLWINDOW *AssociatedControl(DBOX *db, enum commands Tcmd)
  705. {
  706.     CTLWINDOW *ct = db->ctl;
  707.     while (ct->class)    {
  708.         if (ct->class != TEXT)
  709.             if (ct->command == Tcmd)
  710.                 break;
  711.         ct++;
  712.     }
  713.     return ct;
  714. }
  715.  
  716. static void dbShortcutKeys(WINDOW wnd, DBOX *db, int ky)
  717. {
  718.     CTLWINDOW *ct;
  719.     int ch = AltConvert(ky);
  720.  
  721.     if (ch != 0)    {
  722.         ct = db->ctl;
  723.         while (ct->class)    {
  724.             char *cp = ct->vtext;
  725.             while (cp && *cp)    {
  726.                 if (*cp == SHORTCUTCHAR && tolower(*(cp+1)) == ch)    {
  727.                     if (ct->class == TEXT)
  728.                         ct = AssociatedControl(db, ct->command);
  729.                     if (ct->class == RADIOBUTTON)
  730.                         SetRadioButton(wnd, db, ct);
  731.                     else if (ct->class == CHECKBOX)
  732.                         InvertCheckBox(wnd, ct);
  733.                     else if (ct->class)    {
  734.                         SendMessage(ct->wnd, SETFOCUS, TRUE, 0);
  735.                         if (ct->class == BUTTON)
  736.                             SendMessage(ct->wnd, KEYBOARD, '\r', 0);
  737.                     }
  738.                     return;
  739.                 }
  740.                 cp++;
  741.             }
  742.             ct++;
  743.         }
  744.     }
  745. }
  746.  
  747. static void PressButtons(WINDOW wnd)
  748. {
  749.     CTLWINDOW *ct = wnd->dFocus;
  750.     DBOX *db = wnd->extension;
  751.     if (ct != NULL)    {
  752.         if (ct->class == RADIOBUTTON)
  753.             SetRadioButton(wnd, db, ct);
  754.         else if (ct->class == CHECKBOX)
  755.             InvertCheckBox(wnd, ct);
  756.     }
  757. }
  758.  
  759. /* generic window processor used by all dialog box control windows */
  760. static int ControlProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  761. {
  762.     DBOX *db;
  763.     CTLWINDOW *ct;
  764.  
  765.     if (wnd == NULLWND)
  766.         return FALSE;
  767.     db = GetParent(wnd) ? GetParent(wnd)->extension : NULL;
  768.     ct = db ? ControlBox(db, wnd) : NULL;
  769.  
  770.     if (GetClass(wnd) == BOX)    {
  771.         int rtn;
  772.         switch (msg)    {
  773.             case SETFOCUS:
  774.             case PAINT:
  775.                 return FALSE;
  776.             case LEFT_BUTTON:
  777.             case BUTTON_RELEASED:
  778.                 return SendMessage(GetParent(wnd), msg, p1, p2);
  779.             case BORDER:
  780.                 rtn = DefaultWndProc(wnd, msg, p1, p2);
  781.                 if (ct->itext != NULL)
  782.                     writeline(wnd, ct->itext, 1, 0, FALSE);
  783.                 return rtn;
  784.             default:
  785.                 break;
  786.         }
  787.     }
  788.     switch (msg)    {
  789.         case KEYBOARD:
  790.             switch ((int) p1)    {
  791.                 case '\r':
  792.                     if (GetClass(wnd) == EDITBOX && !isMultiLine(wnd))    {
  793.                         SendMessage(GetParent(wnd), COMMAND, ID_OK, 0);
  794.                         return TRUE;
  795.                     }
  796.                     break;
  797. #ifdef INCLUDE_HELP
  798.                 case F1:
  799. #ifdef INCLUDE_SYSTEM_MENUS
  800.                     if (WindowMoving || WindowSizing)
  801.                         break;
  802. #endif
  803.                     if (!DisplayHelp(wnd, ct->help))
  804.                         SendMessage(GetParent(wnd), COMMAND, ID_HELP, 0);
  805.                     return TRUE;
  806. #endif
  807.                 default:
  808.                     break;
  809.             }
  810.             break;
  811.         case SETFOCUS:
  812.             if (GetClass(wnd) != BUTTON)    {
  813.                 if (p1)    {
  814.                     DefaultWndProc(wnd, msg, p1, p2);
  815.                     SendMessage(GetParent(wnd), COMMAND,
  816.                         inFocusCommand(db), ENTERFOCUS);
  817.                     return TRUE;
  818.                 }
  819.                 else 
  820.                     SendMessage(GetParent(wnd), COMMAND,
  821.                         inFocusCommand(db), LEAVEFOCUS);
  822.             }
  823.             break;
  824.         case CLOSE_WINDOW:
  825.             if (db != NULL && ct != NULL)    {
  826.                 WINDOW pwnd = GetParent(wnd);
  827.                 if (ct->vtext != NULL && ct->class == TEXT)    {
  828.                     free(ct->vtext);
  829.                     ct->vtext = NULL;
  830.                 }
  831.                 if (pwnd && pwnd->ReturnCode == ID_OK &&
  832.                                 ct->class == EDITBOX) {
  833.                     if (wnd->TextChanged)    {
  834.                         int len = strlen(wnd->text);
  835.                         ct->itext = realloc(ct->itext, len+1);
  836.                         if (ct->itext != NULL)
  837.                             strcpy(ct->itext, wnd->text);
  838.                     }
  839.                 }
  840.             }
  841.             break;
  842.         default:
  843.             break;
  844.     }
  845.     return DefaultWndProc(wnd, msg, p1, p2);
  846. }
  847.  
  848. #endif
  849.  
  850. /* ----- Create unambiguous path from file spec, filling in the
  851.      drive and directory if incomplete. Optionally change to
  852.      the new drive and subdirectory ------ */
  853. void CreatePath(char *path, char *fspec, int InclName, int Change)
  854. {
  855.     int cm = 0;
  856.     unsigned currdrive;
  857.     char currdir[64];
  858.     char *cp;
  859.  
  860.     if (!Change)    {
  861.         /* ----- save the current drive and subdirectory ----- */
  862. #if MSC | WATCOM
  863.         _dos_getdrive(&currdrive);
  864.         currdrive -= 1;
  865. #else
  866.         currdrive = getdisk();
  867. #endif
  868.         getcwd(currdir, sizeof currdir);
  869.         memmove(currdir, currdir+2, strlen(currdir+1));
  870.         cp = currdir+strlen(currdir)-1;
  871.         if (*cp == '\\')
  872.             *cp = '\0';
  873.     }
  874.  
  875.     *drive = *dir = *name = *ext = '\0';
  876. #ifndef MSC
  877. #ifndef WATCOM
  878.     cm =
  879. #endif
  880. #endif
  881.     fnsplit(fspec, drive, dir, name, ext);
  882.     if (!InclName)
  883.         *name = *ext = '\0';
  884.     *drive = toupper(*drive);
  885.  
  886. #if MSC | WATCOM
  887.     if (*ext)
  888.         cm |= EXTENSION;
  889.     if (InclName && *name)
  890.         cm |= FILENAME;
  891.     if (*dir)
  892.         cm |= DIRECTORY;
  893.     if (*drive)
  894.         cm |= DRIVE;
  895. #endif
  896.  
  897.     if (cm & DRIVE)
  898.         setdisk(*drive - 'A');
  899.     else     {
  900. #if MSC | WATCOM
  901.         _dos_getdrive((unsigned *)drive);
  902.         *drive -= 1;
  903. #else
  904.         *drive = getdisk();
  905. #endif
  906.         *drive += 'A';
  907.     }
  908.  
  909.     if (cm & DIRECTORY)    {
  910.         cp = dir+strlen(dir)-1;
  911.         if (*cp == '\\')
  912.             *cp = '\0';
  913.         chdir(dir);
  914.     }
  915.     getcwd(dir, sizeof dir);
  916.     memmove(dir, dir+2, strlen(dir+1));
  917.  
  918.     if (InclName)    {
  919.         if (!(cm & FILENAME))
  920.             strcpy(name, "*");
  921.         if (!(cm & EXTENSION))
  922.             strcpy(ext, ".*");
  923.     }
  924.     else
  925.         *name = *ext = '\0';
  926.     if (dir[strlen(dir)-1] != '\\')
  927.         strcat(dir, "\\");
  928.     memset(path, 0, sizeof path);
  929.     fnmerge(path, drive, dir, name, ext);
  930.  
  931.     if (!Change)    {
  932.         setdisk(currdrive);
  933.         chdir(currdir);
  934.     }
  935. }
  936.  
  937. static void ChangeFocus(WINDOW wnd, int direc)
  938. {
  939.     DBOX *db = wnd->extension;
  940.      CTLWINDOW *ct = db->ctl;
  941.      CTLWINDOW *ctt;
  942.  
  943.     /* --- find the control that has the focus --- */
  944.     while (ct->class)    {
  945.         if (ct == wnd->dFocus)
  946.             break;
  947.         ct++;
  948.     }
  949.     if (ct->class)    {
  950.         ctt = ct;
  951.         do    {
  952.             /* ----- point to next or previous control ----- */
  953.             if (direc)    {
  954.                 ct++;
  955.                 if (ct->class == 0)
  956.                     ct = db->ctl;
  957.             }
  958.             else    {
  959.                 if (ct == db->ctl)
  960.                     while (ct->class)
  961.                         ct++;
  962.                 --ct;
  963.             }
  964.  
  965.             if (ct->class != BOX && ct->class != TEXT)    {
  966.                 wnd->dFocus = ct;
  967.                 if (ctt->wnd == NULLWND)
  968.                     SendMessage(wnd, PAINT, 0, (PARAM) ctt);
  969.                 if (ct->wnd == NULLWND)
  970.                     SendMessage(wnd, PAINT, 0, (PARAM) ct);
  971.                 SendMessage(ct->wnd ? ct->wnd : wnd, SETFOCUS, TRUE, 0);
  972.                 break;
  973.             }
  974.         } while (ct != ctt);
  975.     }
  976. }
  977.